Skip to content

Fix immutables generation#3

Merged
eggy03 merged 5 commits into
masterfrom
fix-immutables-generation
Apr 21, 2026
Merged

Fix immutables generation#3
eggy03 merged 5 commits into
masterfrom
fix-immutables-generation

Conversation

@eggy03
Copy link
Copy Markdown
Owner

@eggy03 eggy03 commented Apr 21, 2026

Description

Fixed leaking of Immutables generated immutable implementations of abstract classes via service classes, to the public API

Type of Change

Bug fix

Before Immutables was introduced, entity classes were not abstract and did not have the Abstract* prefix either. They were concrete classes and the service classes had these concrete classes as their return type, for example List<DMIProcessor> get();.

After Immutables was introduced, the entity classes were turned into abstract classes and would have the Abstract* prefix in their name. Immutables would scan this and create generated immutable implementations after removing the Abstract* prefix. So, an abstract class AbstractDMIProcessor.class would have an immutable implementation called DMIProcessor.class. This was fine, but entity naming meant the service classes should have returned the abstract instances. Instead, the return type of the service classes retained the pre-Immutable naming scheme, which meant, service classes would now return generated concrete implementations, instead of the actual abstract entities. This caused a leakage of immutable entities to the public API.

It was originally intended for the service classes to de-serialize a JSON to it's immutable instance but return the abstract instance, since all immutable generated sources extend the abstract classes. If there was a need to build a custom instance, something like the following would have been the preferred choice:

DMIProcessor processor = new ImmutableDMIProcessor.Builder().build();
// or
DMIProcessor processor = ImmutableDMIProcessor.copyOf(someOtherProcessor).withSomeMethod(someValue);

where DMIProcessor represents the abstract class and ImmutableDMIProcessor is the generated immutable implementation.

To achieve this, the Abstract* prefix from all the abstract classes have been removed, and Immutable* prefix has been added to all generated immutable implementations. Additionally, two Jackson annotations called @JsonSerialize(as = ImmutableSomeName.class) and @JsonDeserialize(as = ImmutableSomeName.class) has been added to all the entity classes.
These annotations tell the Jackson mappers in the mapping layer to deserialize or serialize the input JSON as the immutable implementations, but when returning the value to the service layer, which is eventually returned to the user, it should be referenced via the abstract entity only.

JSON -> ImmutableDMIProcessor(mapping layer) -> DMIProcessor(service layer)

Obviously, this means you will not be able to access the builder methods, which is intended, because to create your custom builder, you must invoke the Immutable implementations directly. The abstract reference only contains the immutable field values.

Note that this is a BREAKING CHANGE

Breaking Change

  • toString() in entity classes no longer returns a pretty-printed JSON. The function has been delegated to toJson() instead.

eggy03 added 5 commits April 20, 2026 20:53
- Couldn't find if --json flag could actually make it to release in dmidecode

Signed-off-by: Egg-03 <111327101+eggy03@users.noreply.github.com>
- Remove `@JsonSerialize` annotation as it will be applied individually on entity classes.
- Modify `typeAbstract` style to remove the "Abstract" prefix, allowing for cleaner abstract class naming.
- Update `typeImmutable` style to add an "Immutable" prefix to generated immutable types.
- The current setup leaks the implementations to the public API by default. While mappers need concrete implementation during serialization and deserialization, the final reference must be held by the abstract class itself.
- This update to style will allow the abstract classes to have names starting with DMI*, while serialization and deserialization will happen in the mapping layer, with the implemented classes, but they will retain the references of their abstract counterparts which will be returned.

Signed-off-by: Egg-03 <111327101+eggy03@users.noreply.github.com>
…otations

- Rename abstract DMI entity classes to their concrete counterparts (e.g., `AbstractDMIProcessor` to `DMIProcessor`).
- Add manual `@JsonSerialize` and `@JsonDeserialize` annotations to the renamed classes to specify the immutable implementation for Jackson serialization/deserialization.
- Remove example builder code blocks from Javadoc comments as they are no longer relevant to abstract classes.

Signed-off-by: Egg-03 <111327101+eggy03@users.noreply.github.com>
- Replace usage of `Builder()` with `Immutable<EntityName>.Builder()` in various test classes.
- This change aligns the tests with the use of immutable data structures for DMI entities.
- Updated files include:
    - `DMIProcessorServiceTest.java`
    - `DMISystemServiceTest.java`
    - `DMIPortableBatteryServiceTest.java`
    - `DMICacheServiceTest.java`
    - `DMIBIOSServiceTest.java`
    - `DMIBaseboardServiceTest.java`
    - `DMIMemoryDeviceServiceTest.java`
    - `DMIPhysicalMemoryArrayServiceTest.java`
    - `DMISystemSlotsServiceTest.java`
    - `DMIChassisServiceTest.java`
    - `DMIPortConnectorInformationServiceTest.java`
    - `DMIBIOSLanguageServiceTest.java`

Signed-off-by: Egg-03 <111327101+eggy03@users.noreply.github.com>
- toString() no more returns a pretty-printed JSON. The function has been delegated to `toJson()` instead

Signed-off-by: Egg-03 <111327101+eggy03@users.noreply.github.com>
@eggy03 eggy03 merged commit a340e10 into master Apr 21, 2026
1 check passed
@eggy03 eggy03 deleted the fix-immutables-generation branch April 21, 2026 04:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant